package com.cskaoyan.javase.object._1tostring;

/**
 * @description: toString方法
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * toString方法的声明:
 *       public String toString()
 * 没有特别需要注意的,唯一需要注意的是它是有返回值,并且返回值类型是String
 *
 * 方法的作用:
 *  -该方法需要某个对象去调用,返回该对象的字符串（String）表示
 * - 通常，toString 方法会返回一个“以文本方式表示”此对象的字符串
 * - 结果应是一个简明但易于读懂的信息表达式
 * - 建议所有子类都重写此方法
 *
 * Object类当中的toString方法实现:
 *      return this.getClass().getName() + "@" + Integer.toHexString(hashCode());
 * 解释:
 *      getClass().getName() 获取该类型的全限定类名
 *      hashCode()称之为哈希方法,它会返回该对象地址值的十进制表示
 *      Integer.toHexString(hashCode()) 把地址值的十进制数转换成十六进制字符串
 *      连起来:
 *          返回"类的全限定类名 + @ + 地址值的十六进制表示"
 *
 * 实际上,当我们直接用输出语句打印对象名/数组名/引用等时
 *      会自动调用Object类当中toString()方法(在子类没有自己重写方法的时候)
 *
 * 多数情况下,我们不太关注地址值和全限定类名,所以需要自己在子类中重写toString方法
 * 重写toString方法的一般规则:
 *      打印成员变量的取值
 *      类名{
 *          '成员变量' = 取值,
 *      }
 * 注意事项:
 *      1.toString方法重写后一般都是打印成员变量的取值,不要乱写toString方法,否则会带来一些问题
 *          比如Debug模式走过创建对象,或者对象调用方法时,会自动调用toString方法打印对象的信息
 *          如果乱写toString方法会导致不可预知的后果
 *          推荐使用快捷键生成,而不是手写 alt+insert
 *      2.任何位置,只要使用"对象名"做字符串相关操作,都会自动调用toString()方法
 *          比如用对象名+字符串
 *      3.如果类中有引用数据类型的成员变量,必要时也需要重写它的toString方法
 *      4.自动隐含调用的toString方法不要写出来,写出来很容易会导致空指针异常,而不写出来是不会空指针异常的
 *            不要"画蛇添足"
 *
 */
public class Demo {
    public static void main(String[] args) {
        /*int[] arr = new int[3];
        //Implicit call to 'toString()' on array 'arr'
        System.out.println(arr.toString());*/

        /*//创建Student对象
        Student s = new Student("张四", 18, 100);
        System.out.println(s);
        System.out.println(s.age);

        System.out.println(s + "hello world!");*/

        //创建Student对象
        Student s = new Student("小明", 8, 99, new Pet(2, 2000));
        System.out.println(s);
        Student s2 = new Student("长风", 18, 100, null);
        System.out.println(s2);

    }
}

class Student {
    String name;
    int age;
    double score;
    //引用数据类型的成员变量
    Pet p;

    public Student() {
    }

    public Student(String name, int age, double score, Pet p) {
        this.name = name;
        this.age = age;
        this.score = score;
        this.p = p;
    }

    /*@Override
    public String toString() {
        //age = 500;
        return "Student{" + "name = " + this.name + ",age = " + this.age + ",score" + this.score +
                "}";
    }*/

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                ", Pet = " + p +
                '}';
    }
}

class Pet {
    int age;
    double price;

    public Pet() {
    }

    public Pet(int age, double price) {
        this.age = age;
        this.price = price;
    }

    //重写Pet类的toString方法

    @Override
    public String toString() {
        return "Pet{" +
                "age=" + age +
                ", price=" + price +
                '}';
    }
}
